/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package conceitosgame.util;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.swing.JOptionPane;

/**
 *
 * @author jeferson
 */
public class DesenharImagem {

    private int mascara[][];

    public BufferedImage definirBufferedImage(FormatoBmp bmp) {
        int largura = Conversoes.byteArray2Int4(bmp.BiWidth);
        int altura = Conversoes.byteArray2Int4(bmp.BiHeight);

        BufferedImage imagem = new BufferedImage(largura, altura, BufferedImage.TYPE_INT_ARGB);
        imagem = definirImagem(imagem, bmp);
        return imagem;
    }

    public BufferedImage definirImagem(BufferedImage imagem, FormatoBmp bmp) {

        Graphics ponto = imagem.getGraphics().create();

        byte[] BMPdados = bmp.imagem;//retornabytes(formatoBmp.paleta);
        int largura = Conversoes.byteArray2Int4(bmp.BiWidth);
        int altura = Conversoes.byteArray2Int4(bmp.BiHeight);
        int posicaoPaleta, R, G, B;
        int cont = 0;
        int deslocamento = 0;
        int bitsImagem = Conversoes.byteArray2Short(bmp.BiBitCount);
//        int bitsImagem = 8;
        /*
         * A variável deslocamento eh utilizada para se ignorar os bytes
         * utilizados para o preenchimento da linha, requerimento do formato BMP
         * onde se diz que o número de posições em uma linha tem que ser
         * multiplo de 4
         */
        if ((largura % 4) != 0) {
            deslocamento = 4 - (largura % 4);
        }

        //Caso a imagem seja de 8 bits
        if (bitsImagem == 8) {
            Cores[] paleta = bmp.paleta;
            //percorre a imagem ao contrario
            for (int posicaoLinha = altura; posicaoLinha > 0; posicaoLinha--) {
                for (int posicaoColuna = 0; posicaoColuna < largura; posicaoColuna++) {
                    posicaoPaleta = BMPdados[cont] & 0xFF;

                    B = (paleta[posicaoPaleta].getB());
                    G = (paleta[posicaoPaleta].getG());
                    R = (paleta[posicaoPaleta].getR());
                    Color cor = new Color(R, G, B);

                    ponto.setColor(cor);
                    ponto.drawLine(posicaoColuna, posicaoLinha, posicaoColuna, posicaoLinha);
                    cont++;
                }
                cont += deslocamento;
            }
        }

        //Imagem em 24 bits        
        if (bitsImagem == 24) {
            int deslocamentoColuna = 0;

            if ((largura % 4) != 0) {
                deslocamento = (4 - ((largura * 3) % 4));
            }

            for (int posicaoLinha = altura; posicaoLinha > 0; posicaoLinha--) {
                for (int posicaoColuna = 0; posicaoColuna < largura; posicaoColuna++) {

                    B = ((int) BMPdados[deslocamentoColuna++]) & 0xFF;
                    G = ((int) BMPdados[deslocamentoColuna++]) & 0xFF;
                    R = ((int) BMPdados[deslocamentoColuna++]) & 0xFF;
                    Color cor = new Color(R, G, B);

                    ponto.setColor(cor);
                    ponto.drawLine(posicaoColuna, posicaoLinha, posicaoColuna, posicaoLinha);

                }
                deslocamentoColuna = deslocamentoColuna + deslocamento;
            }
        }
        if (bitsImagem > 24) {
            JOptionPane.showMessageDialog(null, "Imagem com mais de 24 bits: não é possível abri-la");
        }
        if (bitsImagem < 8) {
            JOptionPane.showMessageDialog(null, "Imagem com menos de 8 bits");
        }

        return imagem;
    }

    public FormatoBmp composicao(FormatoBmp fundo, FormatoBmp frente) {
        FormatoBmp copiaFundo = new FormatoBmp();
        copiaFundo.copiarBmp(fundo);
        int largura = Conversoes.byteArray2Int4(frente.BiWidth);
        int altura = Conversoes.byteArray2Int4(frente.BiHeight);
        int deslocamento = 0, deslocamentoColunaFrente = 0, deslocamentoColunaFundo = 0, R, B, G;
        Color corFrente, corFundo;
        obterMascara(frente);
//        passaBaixa(mascara, altura, largura);

        if ((largura % 4) != 0) {
            deslocamento = (4 - ((largura * 3) % 4));
        }

        for (int posicaoLinha = altura - 1; posicaoLinha >= 0; posicaoLinha--) {
            for (int posicaoColuna = 0; posicaoColuna < largura; posicaoColuna++) {
                B = ((int) frente.imagem[deslocamentoColunaFrente++] & 0xFF);
                G = ((int) frente.imagem[deslocamentoColunaFrente++] & 0xFF);
                R = ((int) frente.imagem[deslocamentoColunaFrente++] & 0xFF);
                corFrente = new Color(R, G, B);

                B = ((int) fundo.imagem[deslocamentoColunaFundo++] & 0xFF);
                G = ((int) fundo.imagem[deslocamentoColunaFundo++] & 0xFF);
                R = ((int) fundo.imagem[deslocamentoColunaFundo++] & 0xFF);
                corFundo = new Color(R, G, B);

                corFundo = funcaoAlfa(posicaoLinha, posicaoColuna, corFrente, corFundo);
                copiaFundo.imagem[deslocamentoColunaFundo - 1] = (byte) corFundo.getRed();
                copiaFundo.imagem[deslocamentoColunaFundo - 2] = (byte) corFundo.getGreen();
                copiaFundo.imagem[deslocamentoColunaFundo - 3] = (byte) corFundo.getBlue();
            }
            deslocamentoColunaFrente = deslocamentoColunaFrente + deslocamento;
            deslocamentoColunaFundo = deslocamentoColunaFundo + deslocamento;
        }
//        return definirBufferedImage(fundo);
        return copiaFundo;
    }

    private Color funcaoAlfa(int x, int y, Color frente, Color fundo) {
        int R, G, B;
        R = (((1 - (mascara[x][y] / 255)) * fundo.getRed()) + ((mascara[x][y] / 255) * frente.getRed()));
        G = (((1 - (mascara[x][y] / 255)) * fundo.getGreen()) + ((mascara[x][y] / 255) * frente.getGreen()));
        B = (((1 - (mascara[x][y] / 255)) * fundo.getBlue()) + ((mascara[x][y] / 255) * frente.getBlue()));
        return new Color(R, G, B);
    }

    private void obterMascara(FormatoBmp imagem) {
        int largura = Conversoes.byteArray2Int4(imagem.BiWidth);
        int altura = Conversoes.byteArray2Int4(imagem.BiHeight);
        mascara = new int[altura][largura];
        int deslocamento = 0, deslocamentoColuna = 0, R, G, B;

        if ((largura % 4) != 0) {
            deslocamento = (4 - ((largura * 3) % 4));
        }

        for (int posicaoLinha = altura - 1; posicaoLinha >= 0; posicaoLinha--) {
            for (int posicaoColuna = 0; posicaoColuna < largura; posicaoColuna++) {
                B = ((int) imagem.imagem[deslocamentoColuna++] & 0xFF);
                G = ((int) imagem.imagem[deslocamentoColuna++] & 0xFF);
                R = ((int) imagem.imagem[deslocamentoColuna++] & 0xFF);

                if (!((R == 0) && (G == 0) && (B == 255))) {
                    mascara[posicaoLinha][posicaoColuna] = 255;
                } else {
                    mascara[posicaoLinha][posicaoColuna] = 0;
                }
            }
            deslocamentoColuna = deslocamentoColuna + deslocamento;
        }
    }

    private void passaBaixa(int Original[][], int altura, int largura) {
        int i, j, l = 0, k = 0;
        int soma = 0;
        int Aux[][] = new int[altura + 2][largura + 2];    //Matriz auxiliar que contém 1 linha e coluna a mais
        //Copiando valores da matriz original para matriz auxiliar, onde linha e coluna incrementadas são uma cópia de seus vizinhos
        Aux[0][0] = Original[0][0];
        Aux[altura + 1][0] = Original[altura - 1][0];
        Aux[0][largura + 1] = Original[0][largura - 1];
        Aux[altura + 1][largura + 1] = Original[altura - 1][largura - 1];

        for (i = 1; i <= altura; i++) {   //preenche os elementos das bordas das laterais
            Aux[i][0] = Original[i - 1][0];
            Aux[i][largura + 1] = Original[i - 1][largura - 1];
        }

        for (i = 1; i <= largura; i++) {  //preenche os elementos das bordas superior e inferior
            Aux[0][i] = Original[0][i - 1];
            Aux[altura + 1][i] = Original[altura - 1][i - 1];
        }

        for (i = 1; i <= altura; i++) {
            for (j = 1; j <= largura; j++) {
                Aux[i][j] = Original[i - 1][j - 1];
            }
        }

        for (i = 0; i < altura; i++) {
            for (j = 0; j < largura; j++) {
                for (k = i; k < i + 2; k++) {
                    for (l = j; l < (j + 2); l++) {
                        soma += Aux[k][l];
                    }
                }
                soma = soma / 4;    //calculo da média
                Original[i][j] = soma;
                soma = 0;
            }
        }
        mascara = Original;
    }

    public int[][] obterMascaraPintura(FormatoBmp bmp, Color corAntiga) {
        int largura = Conversoes.byteArray2Int4(bmp.BiWidth);
        int altura = Conversoes.byteArray2Int4(bmp.BiHeight);
        int[][] mascaraPintura = new int[altura][largura];

        int deslocamento = 0, deslocamentoColuna = 0, R, G, B;

        if ((largura % 4) != 0) {
            deslocamento = (4 - ((largura * 3) % 4));
        }

        for (int posicaoLinha = altura - 1; posicaoLinha >= 0; posicaoLinha--) {
            for (int posicaoColuna = 0; posicaoColuna < largura; posicaoColuna++) {
                B = ((int) bmp.imagem[deslocamentoColuna++] & 0xFF);
                G = ((int) bmp.imagem[deslocamentoColuna++] & 0xFF);
                R = ((int) bmp.imagem[deslocamentoColuna++] & 0xFF);

                if (!((R == corAntiga.getRed()) && (G == corAntiga.getGreen()) && (B == corAntiga.getBlue()))) {
                    mascaraPintura[posicaoLinha][posicaoColuna] = 255;
                } else {
                    mascaraPintura[posicaoLinha][posicaoColuna] = 0;
                }
            }
            deslocamentoColuna = deslocamentoColuna + deslocamento;
        }
        return mascaraPintura;
    }

    public FormatoBmp colorir(int[][] mascara, FormatoBmp imagem, Color cor, int parteCorpo) {
        FormatoBmp retorno = new FormatoBmp();
        retorno.copiarBmp(imagem);
        int r = cor.getRed();
        int g = cor.getGreen();
        int b = cor.getBlue();
        int largura = Conversoes.byteArray2Int4(retorno.BiWidth);
        int altura = Conversoes.byteArray2Int4(retorno.BiHeight);
        int deslocamento = 0;
        int deslocamentoColuna = 0;

        if ((largura % 4) != 0) {
            deslocamento = (4 - ((largura * 3) % 4));
        }

        if (parteCorpo == 1) {
            deslocamentoColuna = 0;
            
            for (int posicaoLinha = altura-1; posicaoLinha > 0; posicaoLinha--) {
                for (int posicaoColuna = 0; posicaoColuna < largura; posicaoColuna++) {

                    if (mascara[posicaoLinha][posicaoColuna] == 0) {
                        retorno.imagem[deslocamentoColuna] = (byte) b;
                        retorno.imagem[deslocamentoColuna+1] = (byte) g;
                        retorno.imagem[deslocamentoColuna+2] = (byte) r;
                        
                    }
                    deslocamentoColuna += 3;
                }
                deslocamentoColuna = deslocamentoColuna + deslocamento;
            }
        }
        if (parteCorpo == 2) {
            deslocamentoColuna = 0;
            
            for (int posicaoLinha = altura-1; posicaoLinha > 0; posicaoLinha--) {
                for (int posicaoColuna = 0; posicaoColuna < largura; posicaoColuna++) {

                    if (mascara[posicaoLinha][posicaoColuna] == 0) {
                        retorno.imagem[deslocamentoColuna] = (byte) b;
                        retorno.imagem[deslocamentoColuna+1] = (byte) g;
                        retorno.imagem[deslocamentoColuna+2] = (byte) r;
                        
                    }
                    deslocamentoColuna += 3;
                }
                deslocamentoColuna = deslocamentoColuna + deslocamento;
            }
        }
        if (parteCorpo == 3) {
            deslocamentoColuna = 0;
            
            for (int posicaoLinha = altura-1; posicaoLinha > 0; posicaoLinha--) {
                for (int posicaoColuna = 0; posicaoColuna < largura; posicaoColuna++) {

                    if (mascara[posicaoLinha][posicaoColuna] == 0) {
                        retorno.imagem[deslocamentoColuna] = (byte) b;
                        retorno.imagem[deslocamentoColuna+1] = (byte) g;
                        retorno.imagem[deslocamentoColuna+2] = (byte) r;
                        
                    }
                    deslocamentoColuna += 3;
                }
                deslocamentoColuna = deslocamentoColuna + deslocamento;
            }
        }
        if (parteCorpo == 4) {
            deslocamentoColuna = 0;
            
            for (int posicaoLinha = altura-1; posicaoLinha > 0; posicaoLinha--) {
                for (int posicaoColuna = 0; posicaoColuna < largura; posicaoColuna++) {

                    if (mascara[posicaoLinha][posicaoColuna] == 0) {
                        retorno.imagem[deslocamentoColuna] = (byte) b;
                        retorno.imagem[deslocamentoColuna+1] = (byte) g;
                        retorno.imagem[deslocamentoColuna+2] = (byte) r;
                        
                    }
                    deslocamentoColuna += 3;
                }
                deslocamentoColuna = deslocamentoColuna + deslocamento;
            }
        }
        if (parteCorpo == 5) {
            deslocamentoColuna = 0;
            
            for (int posicaoLinha = altura-1; posicaoLinha > 0; posicaoLinha--) {
                for (int posicaoColuna = 0; posicaoColuna < largura; posicaoColuna++) {

                    if (mascara[posicaoLinha][posicaoColuna] == 0) {
                        retorno.imagem[deslocamentoColuna] = (byte) b;
                        retorno.imagem[deslocamentoColuna+1] = (byte) g;
                        retorno.imagem[deslocamentoColuna+2] = (byte) r;
                        
                    }
                    deslocamentoColuna += 3;
                }
                deslocamentoColuna = deslocamentoColuna + deslocamento;
            }
        }

        return retorno;
    }
}